package com.example.service;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.common.PageResult;
import com.example.common.enums.ErrorCodeEnum;
import com.example.common.enums.OrdersStatusEnum;
import com.example.common.enums.RoleEnum;
import com.example.exception.CustomException;
import com.example.mapper.PetOrdersMapper;
import com.example.pojo.dto.PetOrdersAddDto;
import com.example.pojo.dto.PetOrdersQueryDto;
import com.example.pojo.entity.*;
import com.example.pojo.vo.PetOrdersQueryVo;
import com.example.utils.AccountUtils;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.List;

/**
 * 宠物订单 service 层实现类
 */
@Service
public class PetOrdersServiceImpl extends ServiceImpl<PetOrdersMapper, PetOrders> implements PetOrdersService{


    @Resource
    private UserService userService;

    @Resource
    private PetShopService petShopService;

    @Resource
    private PetService petService;

    @Resource
    private AddressService addressService;

    /**
     * 创建宠物订单
     *
     * @param dto 宠物订单
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void add(PetOrdersAddDto dto) {
        // 1.校验参数
        if (dto == null) {
            throw new CustomException(ErrorCodeEnum.PARAM_LOST_ERROR);
        }

        // 获取当前登录的账户
        Account currentLoginAccount = AccountUtils.getCurrentLoginAccount();
        if (currentLoginAccount == null) {
            throw new CustomException(ErrorCodeEnum.GET_CUR_USER_ERROR);
        }
        User user = this.userService.lambdaQuery()
                .eq(User::getUsername, currentLoginAccount.getUsername())
                .one();
        // 获取订单的宠物
        Pet pet = this.petService.lambdaQuery()
                .eq(Pet::getId, dto.getPetId())
                .one();

        // 2.生成宠物订单
        PetOrders petOrders = new PetOrders();
        // 2.1 订单号：yyyyMMdd+时问戳
        String ordersNo = DateUtil.format(new Date(), "yyyyMMdd") + System.currentTimeMillis();
        petOrders.setOrderNo(ordersNo);
        // 2.2 普通用户id
        petOrders.setUserId(user.getId());
        // 2.3 宠物店id、宠物id由前端传来
        petOrders.setPetId(dto.getPetId());
        petOrders.setShopId(dto.getShopId());
        // 2.4 宠物名称、宠物图片、宠物价格由宠物id查出
        petOrders.setPetName(pet.getName());
        petOrders.setPetImage(pet.getImage());
        petOrders.setPrice(pet.getPrice());
        // 2.5 收货地址id由前端传来，收货人姓名、收货人地址、收货人电话号由收货地址id查出
        Address address = this.addressService.lambdaQuery()
                .eq(Address::getId, dto.getAddressId())
                .one();
        petOrders.setPickupAddress(address.getAddress());
        petOrders.setPickupName(address.getName());
        petOrders.setPickupPhone(address.getPhone());
        // 2.6 刚创建订单时订单状态为待支付
        petOrders.setStatus(OrdersStatusEnum.CREATED.getName());
        // 2.7 创建时间
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String formatTime = LocalDateTime.now().format(dateTimeFormatter);
        petOrders.setCreateTime(formatTime);

        // 3.将宠物订单存入数据库
        this.save(petOrders);
    }

    /**
     * 分页宠物订单
     *
     * @param pageNum  页码
     * @param pageSize 页大小
     * @param dto      条件
     * @return 分页结果
     */
    @Override
    public PageResult<PetOrdersQueryVo> pageQuery(Integer pageNum, Integer pageSize, PetOrdersQueryDto dto) {
        // 1.校验参数
        if (pageNum == null || pageNum < 1) {
            throw new CustomException(ErrorCodeEnum.PAGE_QUERY_NUM);
        }
        if (pageSize == null || pageSize < 1 || pageSize > 100) {
            throw new CustomException(ErrorCodeEnum.PAGE_QUERY_SIZE);
        }

        // 2.创建 MybatisPlus 分页对象
        IPage<PetOrdersQueryVo> pageObject = new Page<>(pageNum, pageSize);

        // 3.获取当前登录的用户
        Account currentLoginAccount = AccountUtils.getCurrentLoginAccount();
        if (currentLoginAccount == null || StrUtil.isBlank(currentLoginAccount.getRole())) {
            throw new CustomException(ErrorCodeEnum.GET_CUR_USER_ERROR);
        }
        String role = currentLoginAccount.getRole();
        String username = currentLoginAccount.getUsername();

        if (RoleEnum.USER.name().equals(role)) {
            // 4.1 当前登录的用户是普通用户，只查询自己的宠物订单
            Integer userId = this.userService.lambdaQuery()
                    .eq(User::getUsername, username)
                    .one()
                    .getId();
            dto.setUserId(userId);
        } else if (RoleEnum.PETSHOP.name().equals(role)) {
            // 4.2 当前登录的用户是宠物店，只查询自己的宠物订单
            Integer shopId = this.petShopService.lambdaQuery()
                    .eq(PetShop::getUsername, username)
                    .one()
                    .getId();
            dto.setShopId(shopId);
        }
        // 4.3 当前登录的用户是管理员，按条件查询全部的宠物订单

        // 5.分页查询宠物订单
        pageObject = this.getBaseMapper().pageQuery(pageObject, dto);

        // 6.构建分页结果并返回
        return new PageResult<>(
                pageObject.getTotal(),
                pageObject.getRecords()
        );
    }

    /**
     * 根据宠物订单id，查询宠物订单
     *
     * @param id 宠物订单id
     * @return 宠物订单
     */
    @Override
    public PetOrdersQueryVo queryById(Integer id) {
        // 1.校验参数
        if (id == null) {
            throw new CustomException(ErrorCodeEnum.PARAM_LOST_ERROR);
        }
        // 2.根据宠物订单id，查询宠物订单
        PetOrdersQueryDto dto = new PetOrdersQueryDto();
        dto.setId(id);
        return this.getBaseMapper().query(dto).get(0);
    }

    /**
     * 根据条件查询宠物订单
     *
     * @param dto 条件
     * @return 宠物订单列表
     */
    @Override
    public List<PetOrdersQueryVo> queryAll(PetOrdersQueryDto dto) {
        return this.getBaseMapper().query(dto);
    }

    /**
     * 普通用户取消订单
     *
     * @param id 订单id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void cancel(Integer id) {
        // 1.校验订单id
        if (id == null) {
            throw new CustomException(ErrorCodeEnum.PARAM_LOST_ERROR);
        }

        // 2.当前用户只能是普通用户才可以取消订单
        Account currentLoginAccount = AccountUtils.getCurrentLoginAccount();
        if (currentLoginAccount == null) {
            throw new CustomException(ErrorCodeEnum.GET_CUR_USER_ERROR);
        }
        String role = currentLoginAccount.getRole();
        if (!RoleEnum.USER.name().equals(role)) {
            throw new CustomException(ErrorCodeEnum.ONLY_USER_CANCEL);
        }

        // 3.获取订单
        PetOrders dbPetOrders = this.lambdaQuery()
                .eq(PetOrders::getId, id)
                .one();

        // 4.订单状态只有待支付才可以取消订单
        if (!OrdersStatusEnum.CREATED.getName().equals(dbPetOrders.getStatus())) {
            throw new CustomException(ErrorCodeEnum.CANCEL_ONLY_PAY_BEFORE_ERROR);
        }

        // 5.修改宠物订单状态为"已取消"
        this.lambdaUpdate()
                .eq(PetOrders::getId, id)
                .set(PetOrders::getStatus, OrdersStatusEnum.CANCEL.getName())
                .update();
    }

    /**
     * 普通用户支付订单
     *
     * @param id 订单id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void pay(Integer id) {
        // 1.校验订单id
        if (id == null) {
            throw new CustomException(ErrorCodeEnum.PARAM_LOST_ERROR);
        }

        // 2.当前用户只能是普通用户才可以支付订单
        Account currentLoginAccount = AccountUtils.getCurrentLoginAccount();
        if (currentLoginAccount == null) {
            throw new CustomException(ErrorCodeEnum.GET_CUR_USER_ERROR);
        }
        String role = currentLoginAccount.getRole();
        if (!RoleEnum.USER.name().equals(role)) {
            throw new CustomException(ErrorCodeEnum.ONLY_USER_PAY);
        }

        // 3.获取数据
        // 获取订单
        PetOrders dbPetOrders = this.lambdaQuery().eq(PetOrders::getId, id).one();
        // 获取宠物
        Pet dbPet = this.petService.lambdaQuery().eq(Pet::getId, dbPetOrders.getPetId()).one();
        // 获取普通用户
        User dbUser = this.userService.lambdaQuery()
                .eq(User::getId, dbPetOrders.getUserId())
                .one();
        if (dbUser == null) {
            throw new CustomException(ErrorCodeEnum.GET_CUR_USER_ERROR);
        }

        // 普通用户支付订单，变为"待发货"状态，修改宠物库存和普通用户余额
        // 4.修改宠物订单状态
        this.lambdaUpdate()
                .eq(PetOrders::getId, id)
                .set(PetOrders::getStatus, OrdersStatusEnum.PAYED.getName())
                .update();

        // 5.修改宠物库存
        // 5.1 校验宠物是否还有库存
        if (dbPet.getStore() < 1) {
            throw new CustomException(ErrorCodeEnum.PET_STORE_IS_NULL_ERROR);
        }
        // 5.2 宠物库存 - 1
        this.petService.lambdaUpdate()
                .eq(Pet::getId, dbPet.getId())
                .set(Pet::getStore, dbPet.getStore() - 1)
                .update();

        // 6.普通用户余额
        // 6.1 校验普通用户是否还有足够余额
        if (dbUser.getAccount().compareTo(dbPet.getPrice()) < 0) {
            throw new CustomException(ErrorCodeEnum.USER_AMOUNT_NOT_ENOUGH_ERROR);
        }
        // 6.2 普通用户余额 - 宠物价格
        this.userService.lambdaUpdate()
                .eq(User::getId, dbUser.getId())
                .set(User::getAccount, dbUser.getAccount().subtract(dbPet.getPrice()))
                .update();
    }

    /**
     * 宠物店发货
     *
     * @param id 订单id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void send(Integer id) {
        // 1.校验订单id
        if (id == null) {
            throw new CustomException(ErrorCodeEnum.PARAM_LOST_ERROR);
        }

        // 2.当前用户只有是宠物店才可以发货
        Account currentLoginAccount = AccountUtils.getCurrentLoginAccount();
        if (currentLoginAccount == null) {
            throw new CustomException(ErrorCodeEnum.GET_CUR_USER_ERROR);
        }
        String role = currentLoginAccount.getRole();
        if (!RoleEnum.PETSHOP.name().equals(role)) {
            throw new CustomException(ErrorCodeEnum.ONLY_SHOP_SEND);
        }

        // 3.宠物店发货，订单变为"待签收"状态
        this.lambdaUpdate()
                .eq(PetOrders::getId, id)
                .set(PetOrders::getStatus, OrdersStatusEnum.SEND.getName())
                .update();
    }

    /**
     * 普通用户签收
     *
     * @param id 订单id
     */
    @Override
    public void sign(Integer id) {
        // 1.校验订单id
        if (id == null) {
            throw new CustomException(ErrorCodeEnum.PARAM_LOST_ERROR);
        }

        // 2.当前用户只有是普通用户才可以签收
        Account currentLoginAccount = AccountUtils.getCurrentLoginAccount();
        if (currentLoginAccount == null) {
            throw new CustomException(ErrorCodeEnum.GET_CUR_USER_ERROR);
        }
        String role = currentLoginAccount.getRole();
        if (!RoleEnum.USER.name().equals(role)) {
            throw new CustomException(ErrorCodeEnum.ONLY_USER_SIGN);
        }

        // 3.普通用户签收，订单变为"已完成"状态
        this.lambdaUpdate()
                .eq(PetOrders::getId, id)
                .set(PetOrders::getStatus, OrdersStatusEnum.SIGN.getName())
                .update();
    }

    /**
     * 统计宠物销售额
     *
     * @param shopId 宠物店id
     * @param start 开始时间
     * @param end 结束时间
     * @return 宠物销售额
     */
    @Override
    public BigDecimal countSale(Integer shopId, String start, String end) {
        return this.getBaseMapper().countSale(shopId, start, end);
    }
}
